package com.tgu.home_action.service.impl;

import com.tgu.home_action.dao.*;
import com.tgu.home_action.pojo.*;
import com.tgu.home_action.pojo.exception.IMException;
import com.tgu.home_action.pojo.state.RedisHeader;
import com.tgu.home_action.pojo.state.ResponseState;
import com.tgu.home_action.service.AdminService;
import com.tgu.home_action.service.utils.*;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Validated
@Service
public class AdminServiceImpl implements AdminService {
    @Autowired
    private JwtService jwtService;
    @Autowired
    private HttpService httpService;
    @Autowired
    private WXService wxService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private LogMapper logMapper;
    @Autowired
    private Logger logger;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AliYunService aliyunService;
    @Autowired
    private DynamicMapper dynamicMapper;
    @Autowired
    private VolunteerInformationMapper volunteerInformationMapper;
    @Autowired
    private CaseMapper caseMapper;
    @Autowired
    private LiveNessMapper liveNessMapper;
    @Autowired
    private IMService imService;

    /**
     * 管理员登录
     *
     * @param adminBean：登录信息
     * @return token, admin
     */
    @Override
    public ResponseData<Admin> login(Admin adminBean) {
        Admin admin = adminMapper.getUserByUserName(adminBean.getUserName());
        if (admin == null) {
            return new ResponseData<Admin>(ResponseState.USER_NOT_EXIST.getMessage(), ResponseState.USER_NOT_EXIST.getValue());
        }
        if (!passwordEncoder.matches(adminBean.getPassword(), admin.getPassword())) {
            return new ResponseData<Admin>(ResponseState.PASSWORD_IS_ERROR.getMessage(), ResponseState.PASSWORD_IS_ERROR.getValue());
        }
        if (admin.getState() != 1) {
            return new ResponseData<>(ResponseState.ACCOUNT_IS_ILLEGAL.getMessage(), ResponseState.ACCOUNT_IS_ILLEGAL.getValue());
        }
        admin.setRole(Role.getRole(admin.getRoleId()));
        //储存token
        String accessToken = jwtService.getAccessToken(admin.getId(), admin.getRole());
        String refreshToken = jwtService.getRefreshToken(admin.getId(), admin.getRole());
        stringRedisTemplate.opsForValue().set(RedisHeader.ADMIN_TOKEN.getHeader() + admin.getId(), accessToken);
        stringRedisTemplate.expire(RedisHeader.ADMIN_TOKEN.getHeader() + admin.getId(), 2, TimeUnit.HOURS);
        stringRedisTemplate.opsForValue().set(RedisHeader.ADMIN_REFRESH_TOKEN.getHeader() + admin.getId(), refreshToken);
        stringRedisTemplate.expire(RedisHeader.ADMIN_REFRESH_TOKEN.getHeader() + admin.getId(), 15, TimeUnit.DAYS);
        return new ResponseData<Admin>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), accessToken, refreshToken, admin);
    }

    /**
     * 添加管理员
     */
    @Override
    public ResponseData<Admin> addAdmin(Admin adminBean, Admin admin) {
        admin = adminMapper.getById(admin.getId());
        if (adminBean.getRoleId() == 5 || adminBean.getRoleId() == 4) {
            if (admin.getRoleId() != 5) {
                return new ResponseData<>(ResponseState.WITHOUT_PERMISSION.getMessage(), ResponseState.WITHOUT_PERMISSION.getValue());
            }
        } else if (adminBean.getRoleId() == 3) {
            if (admin.getRoleId() != 4 && admin.getRoleId() != 5) {
                return new ResponseData<>(ResponseState.WITHOUT_PERMISSION.getMessage(), ResponseState.WITHOUT_PERMISSION.getValue());
            }
        }
        adminBean.setPassword(passwordEncoder.encode(adminBean.getPassword()));
        adminBean.setRegisterTime(new Timestamp(new Date().getTime()));
        adminMapper.addAdmin(adminBean);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 获取管理员信息
     */
    @Override
    public ResponseData<Admin> getInfo(Admin admin) {
        admin = adminMapper.getById(admin.getId());
        admin.setRole(Role.getRole(admin.getRoleId()));
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), admin);
    }


    /**
     * 添加地域管理员
     */
    @Override
    public ResponseData<Object> addDistrictAdmin(Admin adminBean, Admin admin) {
        adminBean.setRoleId(3);
        adminBean.setPassword(passwordEncoder.encode(adminBean.getPassword()));
        adminBean.setRegisterTime(new Timestamp(new Date().getTime()));
        adminMapper.addAdmin(adminBean);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 修改密码
     */
    @Override
    public ResponseData<Object> updatePassword(@NotNull(message = "newPassword不能为空") String newPassword, @NotNull(message = "oldPassword不能为空") String oldPassword, Admin admin) {
        admin = adminMapper.getById(admin.getId());
        if (admin == null) {
            return new ResponseData<>(ResponseState.USER_NOT_EXIST.getMessage(), ResponseState.USER_NOT_EXIST.getValue());
        }
        if (!passwordEncoder.matches(oldPassword, admin.getPassword())) {
            return new ResponseData<>(ResponseState.PASSWORD_IS_ERROR.getMessage(), ResponseState.PASSWORD_IS_ERROR.getValue());
        }
        admin.setPassword(passwordEncoder.encode(newPassword));
        adminMapper.updatePassword(admin);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 删除管理员
     */
    @Override
    public ResponseData<Object> delete(Integer id, Admin admin) {
        Admin nowAdmin = adminMapper.getById(id);
        if (nowAdmin == null) {
            return new ResponseData<>(ResponseState.ADMIN_NOT_EXIST.getMessage(), ResponseState.ADMIN_NOT_EXIST.getValue());
        }
        if (nowAdmin.getRoleId() == 5) {
            return new ResponseData<>(ResponseState.WITHOUT_PERMISSION.getMessage(), ResponseState.WITHOUT_PERMISSION.getValue());
        } else if (nowAdmin.getRoleId() == 4) {
            if (!admin.getRole().equals("superAdmin")) {
                return new ResponseData<>(ResponseState.WITHOUT_PERMISSION.getMessage(), ResponseState.WITHOUT_PERMISSION.getValue());
            }
        }
        adminMapper.delAdmin(id);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 修改管理员信息
     */
    @Override
    public ResponseData<Object> updateAdminInfo(Admin adminBean, Admin admin) {
        if (adminBean.getState() != null && adminBean.getState() != 0 && adminBean.getState() != 1 && adminBean.getState() != 2) {
            return new ResponseData<>("state只能是1或2", ResponseState.PARAM_IS_ERROR.getValue());
        }
        Admin nowAdmin = adminMapper.getById(adminBean.getId());
        if (nowAdmin == null) {
            return new ResponseData<>(ResponseState.ADMIN_NOT_EXIST.getMessage(), ResponseState.ADMIN_NOT_EXIST.getValue());
        }
        if (nowAdmin.getRoleId() == 5) {
            return new ResponseData<>(ResponseState.WITHOUT_PERMISSION.getMessage(), ResponseState.WITHOUT_PERMISSION.getValue());
        } else if (nowAdmin.getRoleId() == 4) {
            if (!admin.getRole().equals("superAdmin")) {
                return new ResponseData<>(ResponseState.WITHOUT_PERMISSION.getMessage(), ResponseState.WITHOUT_PERMISSION.getValue());
            }
        }
        if (adminBean.getPassword() != null) {
            adminBean.setPassword(passwordEncoder.encode(adminBean.getPassword()));
        }
        adminMapper.updateAdmin(adminBean);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 修改个人地域信息
     */
    @Override
    public ResponseData<Object> updatePlace(Admin adminBean, Admin admin) {
        adminBean.setId(admin.getId());
        adminMapper.updatePlace(adminBean);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 更新token
     */
    @Override
    public ResponseData<Object> refreshToken(@NotNull(message = "refreshToken不能为空") String refreshToken) {
        Admin admin = (Admin) jwtService.getUser(refreshToken);
        if (admin == null) {
            return new ResponseData<>(ResponseState.REFRESH_TOKEN_IS_ERROR.getMessage(), ResponseState.REFRESH_TOKEN_IS_ERROR.getValue());
        }
        String rightToken = stringRedisTemplate.opsForValue().get(RedisHeader.ADMIN_REFRESH_TOKEN.getHeader() + admin.getId());
        if (!refreshToken.equals(rightToken)) {
            return new ResponseData<>(ResponseState.REFRESH_TOKEN_IS_ERROR.getMessage(), ResponseState.REFRESH_TOKEN_IS_ERROR.getValue());
        }
        String newToken = jwtService.getAccessToken(admin.getId(), admin.getRole());
        String newRefreshToken = jwtService.getRefreshToken(admin.getId(), admin.getRole());
        stringRedisTemplate.opsForValue().set(RedisHeader.ADMIN_TOKEN.getHeader() + admin.getId(), newToken, 2, TimeUnit.HOURS);
        stringRedisTemplate.opsForValue().set(RedisHeader.ADMIN_REFRESH_TOKEN.getHeader() + admin.getId(), newRefreshToken, 15, TimeUnit.DAYS);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), newToken, newRefreshToken);
    }

    /**
     * 修改姓名/头像
     */
    @Override
    public ResponseData<Object> updateInfo(Admin adminBean, Admin admin) {
        adminBean.setId(admin.getId());
        adminMapper.updateInfo(adminBean);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 上传图片
     */
    @Override
    public ResponseData<String> uploadPhoto(MultipartFile photo, Admin admin) throws IOException {
        InputStream inputStream = photo.getInputStream();
        if (!FileService.isImage(inputStream)) {
            return new ResponseData<>(ResponseState.FILE_FORMAT_ERROR.getMessage(), ResponseState.FILE_FORMAT_ERROR.getValue());
        }
        photo.getOriginalFilename();
        String url = aliyunService.uploadFile(photo.getInputStream(), "admin/" + admin.getId() + "/" + StringService.getRandomString() + FileService.getFileSuffix(photo.getOriginalFilename()));
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), url);
    }

    /**
     * 分页查询志愿者
     */
    @Override
    public ResponseData<Page<Admin>> getAdmins(Admin admin) {
        Integer sum = adminMapper.getAdminSum(admin);
        if (admin.getPageNo() == null || admin.getPageSize() == null) {
            admin.setPageNo(1);
            admin.setPageSize(sum);
        }
        admin.setStartSize((admin.getPageNo() - 1) * admin.getPageSize());
        List<Admin> admins = adminMapper.getAdmins(admin);
        int pageNum;
        if (admin.getPageSize() == 0) {
            pageNum = 0;
        } else {
            pageNum = sum / admin.getPageSize();
            if (sum % admin.getPageSize() > 0) {
                pageNum++;
            }
        }
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), new Page<>(admin.getPageNo(), admin.getPageSize(), pageNum, sum, admins));
    }

    /**
     * 修改下属管理的头像
     */
    @Override
    public ResponseData<Object> updateAdminAvatar(@NotNull(message = "id不能为空") Integer id, @NotNull(message = "avatarUrl不能为空") String avatarUrl, Admin adminUser) {
        Admin nowAdmin = adminMapper.getById(id);
        if (nowAdmin == null) {
            return new ResponseData<>(ResponseState.ADMIN_NOT_EXIST.getMessage(), ResponseState.ADMIN_NOT_EXIST.getValue());
        }
        if (nowAdmin.getRoleId() == 5) {
            return new ResponseData<>(ResponseState.WITHOUT_PERMISSION.getMessage(), ResponseState.WITHOUT_PERMISSION.getValue());
        } else if (nowAdmin.getRoleId() == 4) {
            if (!adminUser.getRole().equals("superAdmin")) {
                return new ResponseData<>(ResponseState.WITHOUT_PERMISSION.getMessage(), ResponseState.WITHOUT_PERMISSION.getValue());
            }
        }
        adminMapper.updateAvatar(id, avatarUrl);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 通过Id查询管理
     */
    @Override
    public ResponseData<Admin> getAdminById(Integer id) {
        Admin admin = adminMapper.getById(id);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), admin);
    }

    /**
     * 查询动态
     */
    @Override
    public ResponseData<Page<Dynamic>> getDynamic(Dynamic dynamic) {
        Integer sum = dynamicMapper.getSum();
        if (dynamic.getPageNo() == null || dynamic.getPageSize() == null) {
            dynamic.setPageNo(1);
            dynamic.setPageSize(sum);
        }
        dynamic.setStartSize((dynamic.getPageNo() - 1) * dynamic.getPageSize());
        List<Dynamic> dynamics = dynamicMapper.getDynamic(dynamic);
        int pageNum;
        if (dynamic.getPageSize() == 0) {
            pageNum = 0;
        } else {
            pageNum = sum / dynamic.getPageSize();
            if (sum % dynamic.getPageSize() > 0) {
                pageNum++;
            }
        }
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), new Page<>(dynamic.getPageNo(), dynamic.getPageSize(), pageNum, sum, dynamics));

    }

    /**
     * 查询团队指数
     */
    @Override
    public ResponseData<Map<String, Team>> getTeam(Admin admin) throws ParseException {
        Map<String, Team> teamMap = new HashMap<>();
        if (admin.getDistrict() != null) {
            teamMap.put("district", getOneTeam(admin));
        }
        if (admin.getProvince() != null) {
            Admin nowAdmin = new Admin();
            nowAdmin.setProvince(admin.getProvince());
            teamMap.put("province", getOneTeam(nowAdmin));
        }
        teamMap.put("country", getOneTeam(new Admin()));
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), teamMap);
    }

    /**
     * 管理员获取userSig
     */
    @Override
    public ResponseData<String> getUserSig(Admin admin) throws IMException {
        Boolean isExist = imService.accountCheck("admin_" + admin.getId());
        if (!isExist) {
            imService.insertUser("admin_" + admin.getId(), adminMapper.getNameById(admin.getId()), null);
            imService.setMessage("admin_" + admin.getId(), "admin", admin.getId());
        }
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), imService.getUserSig("admin_" + admin.getId()));
    }

    private Team getOneTeam(Admin admin) throws ParseException {
        Team team = new Team();
        //志愿者注册数
        team.setRegisterNum(volunteerInformationMapper.getRegisterNum(admin));
        //完成案件数
        team.setFinishCaseNum(caseMapper.getFinishCaseNumber(admin));
        //案件数
        Integer caseNum = caseMapper.getCaseNumberByPlace(admin);
        //案件完成率
        if(caseNum==0){
            team.setFinishCaseRate((double) 0);
        }else {
            team.setFinishCaseRate((double) (team.getFinishCaseNum() / (double) caseNum));
        }
        //案件完成时间
        team.setFinishCaseTime(caseMapper.getAvgFinishCaseTime(admin));
        //活跃人数
        String todayString = new SimpleDateFormat("yyyy-MM-dd").format(new Date().getTime());
        Timestamp today = new Timestamp(StringService.stingToDate(todayString, "yyyy-MM-dd").getTime());
        Integer liveNum = liveNessMapper.getLiveNessNumByPlace(admin, today);
        //活跃度
        if (team.getRegisterNum() == 0) {
            team.setLiveNess((double) 0);
        } else {
            team.setLiveNess((double) (liveNum / team.getRegisterNum()));
        }
        return team;
    }

}
